# _*_coding:utf-8_*_
import threading
import sys
import os
import traceback

from . import task

from ATS.util import constant
from utils.log_util import loggings
# from ATS.proberdriver import Prober
from ATS.proberdriver import cascade_prober
from ATS.globaldata import gdata
from ATS.errHandler import errHandler
from ATS.datamanager import DataManager

workpath = os.path.dirname(os.path.realpath(sys.argv[0]))
sys.path.insert(0, os.path.dirname(workpath))
sys.path.insert(0, constant.TEST_PATH)

NO_ERR = 0


class EE(threading.Thread):
    """
    Note: tasklist contains simple task only, no parallel and loop task.
    """

    def __init__(self, name, engEvent, engLock):
        threading.Thread.__init__(self)
        self.execDict = {}
        self.setDaemon(True)
        self.run_flag = True
        self.stop_task_flag = False
        self.running = False
        self.name = name
        self.engEvent = engEvent
        self.engLock = engLock
        self.tasklist = []
        self.loopID = None
        # self.prb = Prober.ProberFactory()
        self.init_probe()
        self.clear_err()
        self.init_DataManagerObj()

    def init_probe(self):
        try:
            self.prb = cascade_prober.CascadeProber(constant.PROBE_STATION_ADDRESS)
        except Exception as e:
            raise

    def reset_execDict(self):
        self.execDict['postSingleData'] = self.dmo.postSingleData
        self.execDict['postarraydata'] = self.dmo.postarraydata
        self.execDict['registerBinResult'] = self.dmo.registerBinResult
        self.execDict['addgdata'] = self.dmo.addgdata
        self.execDict['getgdata'] = self.dmo.getgdata
        self.execDict['getCurIni'] = self.dmo.getCurIni
        self.execDict['posterror'] = self.dmo.posterror
        self.execDict['postAllDataForOneLoop'] = self.dmo.postAllDataForOneLoop

    # 修改执行的字典
    def update_execDict(self, test_obj):
        if test_obj.type == task.TEST_TASK:
            loc_info = gdata.get_loc_info(test_obj.locationInd)
            gdata.updateGDD({'siteID': loc_info[1]})

    def gen_RT_execDict(self, test):
        self.update_execDict(test)
        self.execDict.update(gdata.getGDD())

    def gen_service_execDict(self):
        self.execDict.update(gdata.getService())

    def init_DataManagerObj(self):
        self.dmo = DataManager.get_DM()
        # self.dmo = DataManager.DataManager(ee_obj_name=self.name)
        self.reset_execDict()

    def clear_err(self):
        self.err_code = NO_ERR
        self.err_msg = ''

    def stop_EE(self):
        """
        Stop thread function
        """
        self.run_flag = False

    def set_tasks(self, tlist, loopID=None):
        """
        loopID is supported for Loop_Task.
        loopID: "loopUnitStr%d"%loopNum
        """
        self.tasklist = tlist
        print("self.tasklist", self.tasklist, len(self.tasklist))
        self.loopID = loopID
        self.engEvent.clear()
        if self.engLock.locked():
            self.engLock.release()

    def stop_task(self):
        if self.running:
            self.stop_task_flag = True

    def run(self):
        """
        Executed list includes simple task, UAP or Test or Prober Task Only.
        No loop and parallel task.
        """
        while True:
            if not self.run_flag:
                break
            self.running = False
            self.engLock.acquire()
            self.running = True
            ##begin to work
            if not self.tasklist:
                continue
            # TODO execute task list
            for t in self.tasklist:
                if self.stop_task_flag:
                    self.stop_task_flag = False
                    break
                if not self.run_flag:
                    break
                # 探针台task
                # t.type = 2
                if t.type == task.PRB_TASK:  # if t.type==2
                    print("recall dispatch_fun ----------", t.prb_opt)
                    # self.prb.move_first_die()
                    # pass
                    # self.err_code = self.prb.dispatch_fun(t.prb_opt, *t.args)
                    # 分发探针台的动作
                    self.err_code = self.prb.dispatch_fun(t.prb_opt)
                    print("self.err_code", self.err_code)
                    # self.err_code = self.prb.dispatch_fun(502)
                    # print("self.err_code", self.err_code)
                    if self.err_code != NO_ERR:
                        print("error")
                        errHandler.handle_err("EE invoke Prober", self.err_code, self.err_msg)
                        if errHandler.can_ignore(self.err_code):
                            self.clear_err()
                            continue
                        else:
                            break
                # UAP task
                elif t.type == task.UAP_TASK:
                    uapf = os.path.join(constant.UAP_PATH, t.pyfile)
                    self.gen_RT_execDict(t)
                    try:
                        with open(uapf, 'r', encoding="utf-8") as f:
                            exec(f.read(), self.execDict)
                            # exec(uapf, self.execDict)
                        # execfile(uapf, self.execDict)
                    except Exception as e:
                        self.err_code = errHandler.EXEC_UAP_ERR
                        self.err_msg = traceback.format_exc()
                        errHandler.handle_err("EE execute UAP", self.err_code, self.err_msg)
                        if errHandler.can_ignore(self.err_code):
                            self.clear_err()
                            continue
                        else:
                            break
                elif t.type == task.TEST_TASK:
                    testf = os.path.join(constant.TEST_PATH, t.pyfile)
                    # 设置任务
                    self.dmo.set_test(t)
                    self.dmo.clear()  # clear data
                    self.dmo.global_service.update(gdata.getService())
                    self.gen_RT_execDict(t)
                    self.gen_service_execDict()
                    try:
                        if not gdata.getGDD()["Error_site"]:
                            print('##EE execfile:', testf)
                            with open(testf, 'r', encoding="utf-8") as f:
                                exec(f.read())
                                # exec(testf, self.execDict)
                        else:
                            print('Cancel Test as PRMOVE:0 received')
                    except Exception as e:
                        self.err_code = errHandler.EXEC_TEST_ERR
                        self.err_msg = traceback.format_exc()
                        errHandler.handle_err("EE execute test", self.err_code, self.err_msg)
                        if errHandler.can_ignore(self.err_code):
                            self.clear_err()
                            continue
                        else:
                            break
            self.engEvent.set()  # 将event的标志设置为True
